#include "TabBar.h"
#include "../CMD/CmdMgr.h"
#include "../ModuleMgr.h"
#include <core/ImageMgr.h>
#include <core/Events.h>
#include <widgets/SImageButton.h>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QApplication>
#include <QDrag>
#include <QMimeData>
#include <QPropertyAnimation>
#include <QAction>
#include <QMenu>
#include <QToolTip>
#include <QScreen>
#include "core/StyleMgr.h"

static bool s_disable_layout = true;
TabBar::TabBar(QWidget* parent)
	: QWidget(parent)
{
	setAcceptDrops(true);
	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
	setFixedHeight(m_layout.tab_image_height);

#pragma region Test Code
/*
	for (int i = 0; i < 2; ++i)
		addTab(QString::number(i), 0, 0, true);

	for (int i = 2; i < 10; ++i)
		addTab("标签页: " + QString::number(i), 0, 0, false);
		*/
#pragma endregion
	
	QHBoxLayout* layout = new QHBoxLayout();
	layout->setContentsMargins(0, 0, 0, 3);
	layout->setSpacing(0);

	m_btnMore = new SImageButton(this, "guiframe_app_label_more");
	m_btnRefresh = new SImageButton(this, "guiframe_action_refresh");
	m_btnRefresh->setDisabled(true);

	layout->addStretch();
	layout->addWidget(m_btnMore, 0, Qt::AlignBottom);
	layout->addWidget(m_btnRefresh, 0, Qt::AlignBottom);
	setLayout(layout);
	
	m_activePos = 0;
	setMouseTracking(true);
	s_disable_layout = false;

	m_animation = new QPropertyAnimation(this, "animateProgess");
	m_animation->setStartValue(0);
	m_animation->setEndValue(100);
	m_animation->setDuration(200);

	buildActions();
}

void TabBar::layoutTabs(bool reset)
{
	if (s_disable_layout || m_tabs.isEmpty())
		return;

	QRect r = rect();
	//新增tab时，永远加在第一个，需重置隐藏tab
	if (reset)
	{
		for (int pos : m_hideTabs)
		{
			m_tabs[pos].setHide(false);
		}
		m_hideTabs.clear();
		m_layout.showMore = false;
	}

	if(m_layout.showMore)
	{
		int rightBtnWidth = m_layout.right_btn_width * 3;
		int curTabsWidth = 0;
		for (auto tab : m_tabs)
		{
			if (!tab.isHide())
				curTabsWidth += tab.rect.width();
		}
		int leftSpace = rect().width() - rightBtnWidth - curTabsWidth;

		//check right
		for (auto iter = m_hideTabs.begin(); iter != m_hideTabs.end(); ++iter)
		{
			if (*iter < m_activePos)
				continue;

			leftSpace -= m_layout.fixedWidth ? m_layout.normal_tab_width : m_layout.min_tab_width;
			if (leftSpace >= 0)
			{
				m_tabs[*iter].setHide(false);
			}
			else
				break;
		}

		//check left
		for (auto iter = m_hideTabs.rbegin(); iter != m_hideTabs.rend(); ++iter)
		{
			if (*iter > m_activePos)
				continue;

			leftSpace -= m_layout.fixedWidth ? m_layout.normal_tab_width : m_layout.min_tab_width;
			if (leftSpace >= 0)
			{
				m_tabs[*iter].setHide(false);
			}
			else
				break;
		}

		for (auto iter = m_hideTabs.begin(); iter != m_hideTabs.end();)
		{
			if (!m_tabs[*iter].isHide())
				iter = m_hideTabs.erase(iter);
			else
				++iter;
		}
		if (m_hideTabs.isEmpty())
			m_layout.showMore = false;
	}

	//未有隐藏tab时，根据tab数目计算tab宽度
	if (!m_layout.showMore)
	{
		int rightBtnWidth = m_layout.right_btn_width * 2;
		int availableWidth = r.width() - rightBtnWidth;//more & refresh showmore
		int tabsCount = m_tabs.size();
		if (tabsCount > m_fixedCount)
		{
			availableWidth -= m_layout.group_gap;
			availableWidth += (tabsCount - m_fixedCount - 1) * m_layout.tab_overlap;
		}

		//考虑tab重叠
		availableWidth += (m_fixedCount - 1) * m_layout.tab_overlap;

		//激活状态的tab宽度固定
		if (!m_layout.fixedWidth)
		{
			int tabWidth = tabsCount > 1 ? (availableWidth - m_layout.active_tab_width) / (tabsCount - 1) : m_layout.max_tab_width;
			//tabWidth = std::min(tabWidth, m_layout.max_tab_width);
			tabWidth = tabWidth>m_layout.max_tab_width?m_layout.max_tab_width:tabWidth;
			if (tabWidth <= m_layout.min_tab_width)
			{
				tabWidth = m_layout.min_tab_width;
				m_layout.showMore = true;
			}
			m_layout.normal_tab_width = tabWidth;
		}
		else
		{
			if(tabsCount > 1 && m_layout.active_tab_width * (tabsCount - 1) > availableWidth)
				m_layout.showMore = true;
		}
		
	}

	//计算rect
	m_tabsForAnimate = m_tabs;
	int availableWidth = r.width() - (m_layout.right_btn_width * (m_layout.showMore ? 3 : 2));
	QRect tabR(0, 0, m_layout.normal_tab_width, m_layout.tab_image_height);
	for (int i = 0; i < m_tabs.size(); ++i)
	{
		if (m_hideTabs.contains(i))
			continue;
		
		if (i == m_activePos)
			tabR.setWidth(m_layout.active_tab_width);
		else
			tabR.setWidth(m_layout.normal_tab_width);
		m_tabs[i].rect = tabR;

		//固定标签不能隐藏
		if ( i >= m_fixedCount && tabR.right() > availableWidth)
		{
			if(!m_hideTabs.contains(i))
				m_hideTabs.push_back(i);
			m_tabs[i].setHide(true);
			std::sort(m_hideTabs.begin(), m_hideTabs.end());
		}

		if (i == m_fixedCount - 1)
			tabR.moveLeft(tabR.right() + m_layout.group_gap);
		else
			tabR.moveLeft(tabR.right() - m_layout.tab_overlap);
	}

	if (m_fixedCount > 0)
	{
		int x = m_tabs[m_fixedCount - 1].rect.right() - 2;
		m_rectMoveLeft.setRect(x, 12, 14, 14);
		x = m_btnMore->geometry().left() - 4 - 14;
		m_rectMoveRight.setRect(x, 12, 14, 14);
	}

	update();
}

CmdWindowInfo& TabBar::addTab(const QString& title, QWidget* ctrl,int cmdId, bool fixed)
{
	CmdWindowInfo ti;
	ti.title = title;
	ti.cmdId = cmdId;
	ti.widget = ctrl;
	ti.winId = CmdMgr::instance().cmdWindowId();
	if (fixed)
		ti.setFixed(true);

	int index = m_fixedCount;
	m_tabs.insert(index, ti);

	if (!fixed && m_activePos >= m_fixedCount)
		++m_activePos;

	if (fixed)
		++m_fixedCount;

	//调整隐藏tab的索引
	for (int& pos : m_hideTabs)
	{
		++pos;
	}

	int oldTabWidth = m_layout.normal_tab_width;
	activateWindow(index);
	
	int requestReiszeType = -1;
	if (oldTabWidth == m_layout.max_tab_width && m_layout.normal_tab_width < m_layout.max_tab_width)
		requestReiszeType = 0;

	if (requestReiszeType != -1)
		requestResize(requestReiszeType);
	return m_tabs[index];
}

CmdWindowInfo* TabBar::tabById(int tabId)
{
	for (int i = 0; i < m_tabs.size(); ++i)
	{
		if (m_tabs[i].winId == tabId)
			return &(m_tabs[i]);
	}

	return nullptr;
}

int TabBar::tabForCmd(int id, const QString& params)
{
	for (const CmdWindowInfo& ti : m_tabs)
	{
		if (ti.cmdId == id && ti.params.compare(params, Qt::CaseSensitivity::CaseInsensitive) == 0)
			return ti.winId;
	}
	return -1;
}

void TabBar::closeTab(int pos)
{
	if (pos < m_fixedCount)
		return;

	if (!m_dragging)
	{
		tabClose(m_tabs[pos].winId);
	}

	m_hideTabs.removeOne(pos);
	for (int& tabPos : m_hideTabs)
	{
		if(tabPos > pos)
			--tabPos;
	}

	CmdWindowInfo ti = m_tabs[pos];
	m_activeHistory.removeAll(m_tabs[pos].winId);
	m_tabs.erase(m_tabs.begin() + pos);

	//switch active tab
	if (m_activePos == pos)
	{
		if (m_activeHistory.isEmpty())
			m_activePos = 0;
		else
		{
			m_activePos = tabPosById(m_activeHistory.top());
		}	
	}
	else if (m_activePos > pos)
			--m_activePos;

	//TODO:使之前激活的tab显示出来
	if (m_activePos < 0 || m_tabs[m_activePos].isHide())
		m_activePos = 0;

	int oldTabWidth = m_layout.normal_tab_width;

	layoutTabs();
	startAnimation();
	tabActivated(m_tabs[m_activePos].winId);

		
	//TODO:need more accurate
	if (m_layout.normal_tab_width == m_layout.max_tab_width)
		requestResize(1);
}

void TabBar::insertTab(const CmdWindowInfo& ti, int pos)
{
	m_tabs.insert(pos, ti);
	for (int& tabPos : m_hideTabs)
	{
		if (tabPos > pos)
			++tabPos;
	}
	int oldTabWidth = m_layout.normal_tab_width;
	layoutTabs();
	
	int requestReiszeType = -1;
	if (oldTabWidth == m_layout.max_tab_width && m_layout.normal_tab_width < m_layout.max_tab_width)
		requestReiszeType = 0;

	if (requestReiszeType != -1)
		requestResize(requestReiszeType);
}

//TODO: show the hide one
void TabBar::activateWindow(int index)
{
	if (index >= 0 && index < m_tabs.size() && m_activePos != index)
	{
		//if the tab is hidden, show it
		if (m_hideTabs.contains(index))
		{
			//if the tab is in left, hide right tabs firstly
			bool isInLeft = false;
			bool firstVisibleFound = false;
			for (int i = index + 1; i < m_tabs.size(); ++i)
			{
				if (!m_tabs[i].isHide())
				{
					if (!firstVisibleFound)
						firstVisibleFound = true;
					else
					{
						isInLeft = true;
						break;
					}
				}
			}

			m_tabs[index].setHide(false);
			m_hideTabs.removeOne(index);
			int hideIndex = -1;
			if (isInLeft)
			{
				for (int i = m_tabs.size() -1; i >= m_fixedCount; --i)
				{
					if (!m_tabs[i].isHide())
					{
						hideIndex = i;
						break;
					}
				}
			}
			else
			{
				for (int i = m_fixedCount; i < m_tabs.size(); ++i)
				{
					if (!m_tabs[i].isHide())
					{
						hideIndex = i;
						break;
					}
				}
			}
			if (hideIndex != -1)
			{
				m_tabs[hideIndex].setHide(true);
				m_hideTabs.push_back(hideIndex);
				std::sort(m_hideTabs.begin(), m_hideTabs.end());
			}


		}

		m_activePos = index;
		stopAnimation();

		layoutTabs();
		m_activeHistory.push(m_tabs[index].winId);
		startAnimation();
		tabActivated(m_tabs[m_activePos].winId);
	}
}

void TabBar::onMoveBtnClicked(bool left)
{
	if (left && checkLeftHide())
	{
		bool hide = false;
		for (int i = m_tabs.size() - 1; i >= m_fixedCount; --i)
		{
			//hide last none active tab 
			if (!hide && i != m_activePos && !m_tabs[i].isHide())
			{
				m_tabs[i].setHide(true);
				m_hideTabs.push_back(i);
				std::sort(m_hideTabs.begin(), m_hideTabs.end());
				hide = true;
				continue;
			}

			if (hide && m_tabs[i].isHide())
			{
				m_tabs[i].setHide(false);
				m_hideTabs.erase(m_hideTabs.begin() + m_hideTabs.indexOf(i));
				std::sort(m_hideTabs.begin(), m_hideTabs.end());
				break;
			}
		}

		layoutTabs();
	}

	if (!left && checkRightHide())
	{
		bool hide = false;
		for (int i = m_fixedCount; i < m_tabs.size(); ++i)
		{
			//hide first none active tab 
			if (!hide && i != m_activePos && !m_tabs[i].isHide())
			{
				m_tabs[i].setHide(true);
				m_hideTabs.push_back(i);
				std::sort(m_hideTabs.begin(), m_hideTabs.end());
				hide = true;
				continue;

			}
			if (hide && m_tabs[i].isHide())
			{
				m_tabs[i].setHide(false);
				m_hideTabs.erase(m_hideTabs.begin() + m_hideTabs.indexOf(i));
				break;
			}
		}
		layoutTabs();
	}
}

bool TabBar::checkLeftHide() const
{
	if (m_hideTabs.isEmpty())
		return false;

	if (m_hideTabs.first() == m_fixedCount || m_hideTabs.first() == m_fixedCount + 1)
		return true;
	
	return false;
}

bool TabBar::checkRightHide() const
{
	if (m_hideTabs.isEmpty())
		return false;

	if (m_hideTabs.last() == m_tabs.size() - 1 || m_hideTabs.last() == m_tabs.size() - 2)
		return true;

	return false;
}

QPixmap TabBar::getDragPixmap() const
{
	if (m_dragTab.widget)
	{
		QScreen* screen = QGuiApplication::primaryScreen();
		QPixmap pm = screen->grabWindow(m_dragTab.widget->winId());
		pm = pm.scaledToWidth(150);
		QPixmap pmCursor = QPixmap(":/guiframe/image/aero_arrow/aero_arrow_normal.png");
		pmCursor = pmCursor.scaled(16,25,Qt::KeepAspectRatio, Qt::SmoothTransformation);
		int cursorW = pmCursor.width();
		int cursorH = pmCursor.height();
		QPixmap newPm(pm.width()+pmCursor.width(), pm.height()+pmCursor.height());
		newPm.fill(Qt::transparent);
		QPainter painter(&newPm);
		painter.drawPixmap(0, 0, pmCursor);
		painter.drawPixmap(cursorW, cursorH, pm.width(),pm.height(), pm);
		QRect border;
		border.setRect(cursorW, cursorH, pm.width()-1, pm.height()-1);
		painter.setPen(Qt::darkGray);
		painter.drawRect(border);

		return newPm;
		/*QPixmap pm = m_dragTab.widget->grab();
		QPixmap newPm(pm.width(), pm.height());
		QPainter painter;
		painter.begin(&newPm);
		painter.setOpacity(0.6);
		painter.drawPixmap(0, 0, pm);
		painter.end();
		return newPm;*/
	}
	return QPixmap::fromImage(*(ImgMgr::instance().image("guiframe_app_logo_title", WidgetStatus::kNormal, 2)->img()));
}

void TabBar::activateTabByTabId(int tabId)
{
	for (int i = 0; i < m_tabs.size(); ++i)
	{
		if (m_tabs[i].winId == tabId)
		{
			activateWindow(i);
			break;
		}
	}
}

void TabBar::updateTabTitle(int tabId, const QString& title)
{
	for (int i = 0; i < m_tabs.size(); ++i)
	{
		if (m_tabs[i].winId == tabId)
		{
			m_tabs[i].title = title;
			break;
		}
	}
	update();
}

void TabBar::attachWidget(CmdWindowInfo cwi)
{
	if (cwi.widget == nullptr)
		return;

	m_dragTab = cwi;
	startDrag();
}

bool TabBar::event(QEvent *event)
{
	if(event->type() == QEvent::ToolTip)
	{
		QHelpEvent* he = static_cast<QHelpEvent*>(event);
		int tabIndex = hitTestTab(he->pos());
		if(tabIndex != -1)
		{
			const CmdWindowInfo& ti = m_tabs[tabIndex];
			QRect txtRect = fontMetrics().boundingRect(ti.title);
			if(txtRect.width() > ti.rect.width() - 6 * 2)
			{
				QToolTip::showText(he->globalPos(), ti.title);	
				return true;
			}
		}

		QToolTip::hideText();
		he->ignore();
		return true;
	}
	else if (event->type() == (QEvent::Type)SSEventType::UserScaleChanged)
	{
		float scale = getAppInstance()->uiScale();
		m_layout.applyScale(scale);
		setFixedHeight(m_layout.tab_image_height + 1);

		layout()->setContentsMargins(0, 0, 0, 3 * scale);
		resize(width(), m_layout.tab_image_height + 1);
		layoutTabs(true);
	}

	return QWidget::event(event);
}

void TabBar::mousePressEvent(QMouseEvent* e)
{
	m_startDragPos = e->globalPos();
	int tabIndex = hitTestTab(e->pos());
	if (tabIndex == -1)
	{
		if (!m_layout.showMore)
			return;

		if (m_rectMoveLeft.contains(e->pos()))
			onMoveBtnClicked(true);
		else if (m_rectMoveRight.contains(e->pos()))
			onMoveBtnClicked(false);

		return;
	}
}

void TabBar::mouseDoubleClickEvent(QMouseEvent* e)
{
	int tabIndex = hitTestTab(e->pos());
	if (tabIndex != -1)
	{
		closeTab(tabIndex);
	}
}

void TabBar::mouseReleaseEvent(QMouseEvent* e)
{
	if(e->button() != Qt::LeftButton)
		return;

	int tabIndex = hitTestTab(e->pos());
	if (tabIndex == -1)
		return;

	int clickIndex = hitTestTab(mapFromGlobal(m_startDragPos));//鼠标点击和释放的位置不同
	if(clickIndex != tabIndex)
		return;

	if (!m_tabs[tabIndex].isFixed())
	{
		QRect r = m_tabs[tabIndex].rect;
		QRect closeR(QPoint(r.right() - m_layout.clost_btn_gap - m_layout.close_btn_width, r.bottom() - m_layout.clost_btn_gap - m_layout.close_btn_width), QSize(m_layout.close_btn_width, m_layout.close_btn_width));
		bool clickOnClose = closeR.contains(e->pos());
		if (clickOnClose)
		{
			closeTab(tabIndex);
			return;
		}
	}

	activateWindow(tabIndex);
}

void TabBar::resizeEvent(QResizeEvent* event)
{
	stopAnimation();
	layoutTabs();
	startAnimation();
}

void TabBar::leaveEvent(QEvent* event)
{
	m_hoverPos = -1;
	//if move too quickly, dragLeaveEvent will not be received!
	if (m_dragging && !rect().contains(mapFromGlobal(QCursor::pos())))
		closeTab(tabPosById(m_dragTab.winId));
	update();
}

void TabBar::dragEnterEvent(QDragEnterEvent* event)
{
	if (event->mimeData()->hasFormat("application/x-dnditemdata") && event->source() == this)
		event->acceptProposedAction();
	else
		event->ignore();
}

void TabBar::dragLeaveEvent(QDragLeaveEvent* event)
{
	closeTab(tabPosById(m_dragTab.winId));
}

void TabBar::dragMoveEvent(QDragMoveEvent* e)
{
	int tabPosX = (e->pos() + m_dragOffset).x();
	doDragMove(tabPosX);
}

void TabBar::dropEvent(QDropEvent* event)
{
	if (event->mimeData()->hasFormat("application/x-dnditemdata") && event->source() == this)
		event->acceptProposedAction();
}

void TabBar::mouseMoveEvent(QMouseEvent* e)
{
	if ((e->buttons().testFlag(Qt::LeftButton)) && (e->globalPos() - m_startDragPos).manhattanLength() >= QApplication::startDragDistance())
	{
		int clickIndex = hitTestTab(mapFromGlobal(m_startDragPos));//检查是否是从首页标签开始drag
		int tabIndex = hitTestTab(e->pos());
		if (tabIndex > 0 && clickIndex > 0)//首页不能动
		{
			m_activePos = tabIndex;
			layoutTabs();
			m_dragTab = m_tabs[tabIndex];
			m_dragOffset = m_dragTab.rect.topLeft() - e->pos();

			startDrag();
		}
	}

	int tabPos = hitTestTab(e->pos());
	bool needUpdate = tabPos != m_hoverPos;
	m_hoverPos = tabPos;

	if (needUpdate)
		update();
}

void TabBar::contextMenuEvent(QContextMenuEvent *event)
{
	int tabIndex = hitTestTab(event->pos());
	if(tabIndex <= 0)
		return;
	
	m_tabMenu = tabIndex;
	QMenu ctxMenu(this);
	ctxMenu.addAction(m_actionRefresh);
	ctxMenu.addAction(m_actionFix);
	ctxMenu.addAction(m_actionClose);
	ctxMenu.addAction(m_actionCloseOthers);
	ctxMenu.addAction(m_actionCloseAll);
	ctxMenu.addAction(m_actionCloseAllBonds);

	const CmdWindowInfo& ti = m_tabs[tabIndex];
	m_actionRefresh->setEnabled(ti.isWeb());

	if(ti.isFixed())
	{
		m_actionFix->setText(tr("取消固定页面"));
		m_actionClose->setEnabled(false);
	}
	else
	{
		m_actionFix->setText(tr("固定页面"));
		m_actionClose->setEnabled(true);
	}

	m_actionCloseOthers->setEnabled(m_tabs.size() > m_fixedCount);
	m_actionCloseAll->setEnabled(m_tabs.size() > m_fixedCount);
	

	ctxMenu.setStyleSheet("QMenu::item { background-color:transparent;border-bottom: 1px solid black; padding:6px 38px 6px 18px}\n"
						"QMenu::item:selected {background-color:#295D5D}\n"
						"QMenu::item:disabled {color:#808080}\n"
                        "QMenu { background-color:#203E3E; color:#FFEBC8; margin:0px}");
	ctxMenu.exec(event->globalPos());
}

int TabBar::leftSpace() const
{
	return rect().width() - m_tabs.last().rect.right() - m_layout.right_btn_width * 2;
}

void TabBar::paintEvent(QPaintEvent* event)
{
	QVector<CmdWindowInfo> tis = m_tabs;
	if (m_animating)
		tis = m_tabsForAnimate;

	if (tis.isEmpty())
		return;

	QStylePainter painter(this);
	for (int i = 0; i < tis.size(); ++i)
	{
		//if (i == m_activePos)
		//	continue;
		drawTab(painter, tis[i], false, m_hoverPos == i	);
	}

	if(m_activePos >= 0 && m_activePos < tis.size())
		drawTab(painter, tis[m_activePos], true, m_hoverPos == m_activePos);

	drawMoveBtns(painter);
}

void TabBar::drawTab(QStylePainter& painter, const CmdWindowInfo& ti, bool isActive, bool isHover)
{
	if (ti.isHide())
		return;

	bool isDraggingTab = m_dragging && ti.winId == m_dragTab.winId;
	if (isDraggingTab)
	{
		painter.save();
		painter.setOpacity(0.8);
	}

	QRect tabRect = ti.rect;
	tabRect.adjust(0, 2, 0, -2);
	int imgGap = m_layout.image_gag;
	if (isActive)
	{
		if (m_dragging && isDraggingTab)
		{
			QPoint pos = mapFromGlobal(QCursor::pos()) + m_dragOffset;
			pos.setY(0);
			tabRect.moveTo(pos);
		}

		/*SImage* img = ImgMgr::instance().image("guiframe_app_label_selected", WidgetStatus::kNormal, devicePixelRatioF());
		if (img)
		{
			QRect imgR = img->rect();
			imgR.adjust(imgGap, 0, -imgGap, 0);
			painter.drawImage(tabRect, *img, imgR);
		}
		else
		{

		}*/
		QLinearGradient lg(ti.rect.left(), ti.rect.bottom(), ti.rect.right(), ti.rect.bottom());
		lg.setColorAt(0, NAME_COLOR("HighLightArea_L1"));
		lg.setColorAt(1, NAME_COLOR("HighLightArea_L2"));
		QPen pen;
		pen.setWidth(2);
		pen.setBrush(lg);
		painter.setPen(pen);
		painter.drawLine(QPoint(ti.rect.left(), ti.rect.bottom()), QPoint(ti.rect.right(), ti.rect.bottom()));
	}
	else
	{
		/*WidgetStatus imgType = isHover ? WidgetStatus::kHover : (ti.isFixed() ? WidgetStatus::kPressed : WidgetStatus::kNormal);
		SImage* imgLeft = ImgMgr::instance().image("guiframe_app_label_left", imgType, devicePixelRatioF());
		SImage* imgMid = ImgMgr::instance().image("guiframe_app_label_mid", imgType, devicePixelRatioF());
		SImage* imgRight = ImgMgr::instance().image("guiframe_app_label_right", imgType, devicePixelRatioF());

		if (imgLeft && imgMid && imgRight)
		{
			int leftWidth = imgLeft->rect().width() - imgGap;
			int rightWidth = imgRight->rect().width() - imgGap;

			QRect imgR = imgLeft->rect();
			imgR.adjust(imgGap, 0, 0, 0);
			
			QRect drawR(ti.rect);
			painter.drawImage(QRect(drawR.left(), drawR.top(), leftWidth, m_layout.tab_image_height), *imgLeft, imgR);

			painter.drawImage(QRect(drawR.left() + leftWidth, drawR.top(), drawR.width() - leftWidth - rightWidth, m_layout.tab_image_height), *imgMid);

			imgR = imgRight->rect();
			imgR.adjust(0, 0, -imgGap, 0);
			painter.drawImage(QRect(drawR.right() - rightWidth, drawR.top(), rightWidth, m_layout.tab_image_height), *imgRight, imgR);

		}
		else
		{

		}*/
		if (isHover) {
			painter.setBrush(QBrush(NAME_COLOR("Hover")));
			painter.setPen(Qt::transparent);
			painter.setRenderHint(QPainter::Antialiasing);//抗锯齿
			painter.drawRoundedRect(tabRect, 4, 4);
		}
	}

	//draw title
	QColor txtColor = NAME_COLOR("TextNormal");
	if(isActive || ti.isFixed())
		txtColor = NAME_COLOR("Highlight");
	//else if(ti.isFixed())
	//	txtColor = NAME_COLOR("Highlight");
	painter.setPen(txtColor);
	QRect txtDrawRect = tabRect/*.adjusted(6 * getAppInstance()->uiScale(),m_layout.image_top_gap,-6 * getAppInstance()->uiScale(),0)*/;
	int align = Qt::AlignCenter | Qt::AlignVCenter;
	if(txtDrawRect.width() < painter.fontMetrics().boundingRect(ti.title).width())
		align = Qt::AlignLeft | Qt::AlignVCenter;

	QFont font = painter.font();
	font.setPixelSize(12);
	font.setBold(true);
	painter.setFont(font);
	painter.drawText(txtDrawRect, align, ti.title);

	//draw close button
	if (!ti.isFixed() && isHover)
	{
		SImage* img = ImgMgr::instance().image(isActive ? "guiframe_app_label_close_select" : "guiframe_app_label_close", WidgetStatus::kNormal, devicePixelRatioF());
		if (img)
		{
			QRect r = tabRect/* ti.rect*/;
			QRect closeR(QPoint(r.right() - m_layout.clost_btn_gap - m_layout.close_btn_width, r.bottom() - m_layout.clost_btn_gap - m_layout.close_btn_width), QSize(m_layout.close_btn_width, m_layout.close_btn_width));
			painter.setRenderHint(QPainter::SmoothPixmapTransform);
			painter.drawImage(closeR, *img);
		}
	}

	if (isDraggingTab)
		painter.restore();
}

void TabBar::drawMoveBtns(QStylePainter& painter)
{
	if (!m_layout.showMore)
		return;

	bool leftEnable = checkLeftHide();
	bool rightEnable = checkRightHide();

	SImage* img = ImgMgr::instance().image("guiframe_app_label_move_left", leftEnable ? WidgetStatus::kNormal : WidgetStatus::kDisabled, devicePixelRatioF());
	painter.drawImage(m_rectMoveLeft, *img);

	img = ImgMgr::instance().image("guiframe_app_label_move_right", rightEnable ? WidgetStatus::kNormal : WidgetStatus::kDisabled, devicePixelRatioF());
	painter.drawImage(m_rectMoveRight, *img);
}

int TabBar::hitTestTab(QPoint pos)
{
	for (int i = 0; i < m_tabs.size(); ++i)
	{
		if (m_tabs[i].isHide())
			continue;

		QRect r = m_tabs[i].rect.adjusted(0, m_layout.image_top_gap, 0, 0);
		if (r.contains(pos))
		{
			return i;
		}
	}
	return -1;
}

int TabBar::tabPosById(int id)
{
	for (int i = 0; i < m_tabs.size(); ++i)
	{
		if (m_tabs[i].winId == id)
			return i;
	}
	return -1;
}

void TabBar::startDrag()
{
	QByteArray itemData;
	QDataStream dataStream(&itemData, QIODevice::WriteOnly);
	dataStream << m_dragTab.winId;
	QMimeData* mimeData = new QMimeData;
	mimeData->setData("application/x-dnditemdata", itemData);

	QDrag* drag = new QDrag(this);//it will be deleteLater
	drag->setMimeData(mimeData);

	QPixmap pm = getDragPixmap();
	drag->setPixmap(QPixmap(":/guiframe/image/dummy.png"));

	//bad code to process snapshot of qb window
	if (m_dragTab.isPopup())
	{
		if (m_dragTab.widget->parent())
		{
			dynamic_cast<QWidget*>(m_dragTab.widget->parent())->hide();
		}
		else
			m_dragTab.widget->hide();
	}
	

	m_dragging = true;
	drag->setDragCursor(pm, Qt::DropAction::IgnoreAction);
	drag->setDragCursor(pm, Qt::DropAction::MoveAction);
	Qt::DropAction da = drag->exec();
	m_dragging = false;

	if (da == Qt::IgnoreAction)
	{
		tabSeperated(m_dragTab);
	}
	else
		tabActivated(m_dragTab.winId);
}

void TabBar::doDragMove(int tabPosX)
{
	int start = 1;//首页位置不变
	int end = m_fixedCount - 1;
	if (!m_dragTab.isFixed())
	{
		start = m_fixedCount;
		end = m_tabs.size() - 1;
	}

	QRect r = m_dragTab.rect;
	r.setWidth(m_layout.active_tab_width);
	r.moveTo(QPoint(tabPosX, 0));

	int insertPos = -1;
	int tabPos = tabPosById(m_dragTab.winId);
	for (int i = start; i <= end; ++i)
	{
		const CmdWindowInfo& ti = m_tabs[i];
		if (ti.isHide() || ti.winId == m_dragTab.winId)
			continue;

		QRect insectRect = ti.rect.intersected(r);
		if (insectRect.isValid())
		{
			if (tabPos == -1)
			{
				if (r.left() > ti.rect.center().x())
					insertPos = i + 1;
				else
					insertPos = i;
			}
			else if (insectRect.left() == ti.rect.left() && insectRect.right() - 5 > ti.rect.center().x())
				insertPos = i + 1;
			else if (insectRect.right() == ti.rect.right() && insectRect.left() + 5 <= ti.rect.center().x())
				insertPos = i;
		}
		if (insertPos != -1)
			break;
		else if (i == m_tabs.size() - 1 && r.left() > ti.rect.right())
			insertPos = i + 1;
	}

	if (insertPos == -1 && !m_dragTab.isFixed() && m_tabs.size() == m_fixedCount)
		insertPos = m_fixedCount;

	if (insertPos > 0)
	{
		bool changed = false;
		if (tabPos == -1)//加入tab
		{
			insertTab(m_dragTab, insertPos);
			changed = true;
		}
		else if(insertPos != tabPos)//移动tab
		{
			if (tabPos < insertPos)
				--insertPos;
			m_tabs.move(tabPos, insertPos);
			changed = true;
		}
		if (changed)
		{
			stopAnimation();
			m_activePos = insertPos;
			layoutTabs();
			startAnimation();
		}
		
	}
	update();
}

void TabBar::onBtnClicked()
{

}

void TabBar::setProgress(int v)
{
	bool needUpdate = false;
	if (v == 100)
		m_animating = false;
	else
	{
		float oldPercent = m_animateProgess / 100.0;
		m_animateProgess = v;
		float percent = v / 100.0;
		for (int i = 0; i < m_tabsForAnimate.size(); ++i)
		{
			QRect& r = m_tabsForAnimate[i].rect;
			QRect rDest = m_tabs[i].rect;

			int originX = (r.x() - oldPercent * rDest.x()) / (1 - oldPercent);
			int posDiff = originX + (rDest.x() - originX) * percent - r.x();


			int originWidth = (r.width() - oldPercent * rDest.width()) / (1 - oldPercent);
			int widthDiff = originWidth + (rDest.width() - originWidth) * percent - r.width();

			if (posDiff != 0 || widthDiff != 0)
				needUpdate = true;

			r.adjust(posDiff, 0, posDiff + widthDiff, 0);
		}
	}
	
	if(needUpdate || v == 100)
		repaint();
}

void TabBar::stopAnimation()
{
	m_animation->stop();
	m_animateProgess = 0;
	m_animating = false;
}

void TabBar::startAnimation()
{
	return;
	m_animateProgess = 0;
	m_animating = true;
	m_animation->start();
}

void TabBar::buildActions()
{
	m_actionRefresh = new QAction(tr("刷新页面"), this);
	connect(m_actionRefresh, &QAction::triggered, this, &TabBar::onAction);

	m_actionFix = new QAction(tr("固定页面"), this);
	connect(m_actionFix, &QAction::triggered, this, &TabBar::onAction);

	m_actionClose = new QAction(tr("关闭页面"), this);
	connect(m_actionClose, &QAction::triggered, this, &TabBar::onAction);

	m_actionCloseOthers = new QAction(tr("关闭其他页面"), this);
	connect(m_actionCloseOthers, &QAction::triggered, this, &TabBar::onAction);

	m_actionCloseAll = new QAction(tr("关闭全部页面"), this);
	connect(m_actionCloseAll, &QAction::triggered, this, &TabBar::onAction);

	m_actionCloseAllBonds = new QAction(tr("关闭全部债券页面"), this);
	connect(m_actionCloseAllBonds, &QAction::triggered, this, &TabBar::onAction);

	connect(m_btnMore, &SImageButton::clicked, this, &TabBar::onAction);
	m_actionCloseAllBonds->setEnabled(false);

	m_actionUnfixAll = new QAction(tr("取消所有固定标签"), this);
	connect(m_actionUnfixAll, &QAction::triggered, this, &TabBar::onAction);

	m_actionFixedTabWidth = new QAction(tr("宽度固定(名称显示较完整)"), this);
	m_actionFixedTabWidth->setCheckable(true);
	connect(m_actionFixedTabWidth, &QAction::triggered, this, &TabBar::onAction);

	m_actionVariantTabWidth = new QAction(tr("宽度变形(标签显示数量较多)"), this);
	m_actionVariantTabWidth->setCheckable(true);
	connect(m_actionVariantTabWidth, &QAction::triggered, this, &TabBar::onAction);

}

void TabBar::showMoreMenu()
{
	m_tabMenu = -1;
	QMenu ctxMenu(this);
	/*
		菜单
		标签操作
			关闭全部页面
			关闭全部债券详情
			取消所有固定标签
		标签显示偏好
			宽度固定(名称显示较完整)
			宽度变形(标签显示数量较多)
	*/
	QAction* label = ctxMenu.addAction(tr("标签操作"));
	label->setEnabled(false);
	ctxMenu.addAction(m_actionCloseAll);
	ctxMenu.addAction(m_actionCloseAllBonds);
	ctxMenu.addAction(m_actionUnfixAll);
	label = ctxMenu.addAction(tr("标签显示偏好"));
	label->setEnabled(false);
	ctxMenu.addAction(m_actionFixedTabWidth);
	ctxMenu.addAction(m_actionVariantTabWidth);

	ctxMenu.setStyleSheet("QMenu::item { background-color:transparent;border-bottom: 1px solid black; padding:6px 38px 6px 18px}\n"
		"QMenu::item:selected {background-color:#295D5D}\n"
		"QMenu::item:disabled {color:#808080}\n"
		"QMenu { background-color:#203E3E; color:#FFEBC8; margin:0px}");

	//设置菜单状态
	m_actionCloseAll->setEnabled(m_tabs.size() > m_fixedCount);
	m_actionUnfixAll->setEnabled(m_fixedCount > 1);
	for (int i = m_fixedCount; i < m_tabs.size(); ++i)
	{
		if (m_tabs[i].cmdId == 20061)
		{
			m_actionCloseAllBonds->setEnabled(true);
			break;
		}
	}
	m_actionFixedTabWidth->setChecked(m_layout.fixedWidth);
	m_actionVariantTabWidth->setChecked(!m_layout.fixedWidth);
	//ctxMenu.exec(m_btnMore->mapToGlobal(m_btnMore->pos()));
	ctxMenu.exec(QCursor::pos());
}

void TabBar::unFixTab(int tabPos)
{
	if(tabPos <=0 || tabPos >= m_tabs.size())
		return;
	if (m_tabs[tabPos].isFixed())
	{
		m_tabs[tabPos].setFixed(false);
		if (m_tabs.size() > m_fixedCount && m_tabs[m_fixedCount].isHide())
		{
			for (int i = m_fixedCount; i < m_tabs.size(); ++i)
			{
				m_tabs[i].setHide(false);
				m_hideTabs.removeOne(i);
			}
		}

		--m_fixedCount;
		m_tabs.move(tabPos, m_fixedCount);

	}
}

void TabBar::onAction()
{
	if(sender() == m_actionFix)
	{
		if(m_tabs[m_tabMenu].isFixed())
		{
			m_tabs[m_tabMenu].setFixed(false);
			if(m_tabs.size() > m_fixedCount && m_tabs[m_fixedCount].isHide())
			{
				for(int i = m_fixedCount; i < m_tabs.size(); ++i)
				{
					m_tabs[i].setHide(false);
					m_hideTabs.removeOne(i);
				}
			}
			
			--m_fixedCount;
			m_tabs.move(m_tabMenu, m_fixedCount);
			
		}
		else
		{
			for(int& tab : m_hideTabs)
			{
				if(tab > m_tabMenu)
					--tab;
			}
			m_tabs[m_tabMenu].setFixed(true);
			m_tabs.move(m_tabMenu, m_fixedCount);
			++m_fixedCount;
		}
		
	}
	else if(sender() == m_actionClose)
	{
		closeTab(m_tabMenu);
	}
	else if(sender() == m_actionCloseAll)
	{
		for(int i = m_tabs.size() - 1; i >= m_fixedCount;--i)
		{
			closeTab(i);
		}
	}
	else if(sender() == m_actionCloseOthers)
	{
		for(int i = m_tabs.size() - 1; i >= m_fixedCount;--i)
		{
			if(i == m_tabMenu)
				continue;
			closeTab(i);
		}
	}
	else if (sender() == m_actionCloseAllBonds)
	{
		for(int i = m_tabs.size() - 1; i >= m_fixedCount;--i)
		{
			if(m_tabs[i].cmdId != 20061)
				continue;
			closeTab(i);
		}
	}
	else if (sender() == m_actionUnfixAll)
	{
		while (m_fixedCount > 1)
		{
			unFixTab(m_fixedCount-1);
		}
	}
	else if (sender() == m_actionFixedTabWidth)
	{
		m_layout.fixedWidth = true;
		m_layout.normal_tab_width = m_layout.active_tab_width;
	}
	else if (sender() == m_actionVariantTabWidth)
	{
		m_layout.fixedWidth = false;
	}
	else if (sender() == m_btnMore)
	{
		showMoreMenu();
	}

	if(sender() != m_actionRefresh)
		layoutTabs(sender() == m_actionFixedTabWidth || sender() == m_actionVariantTabWidth);
}


